package com.wechat.api;

import static com.wechat.api.URLPool.*;

import java.util.Date;
import java.util.Map;

import org.springframework.util.Assert;

import com.google.common.collect.Maps;
import com.util.https.HttpsUtil;
import com.wechat.data.AccessToken;
import com.wechat.data.JsapiTicket;
import com.wechat.data.WechatEnv;

import it.sauronsoftware.cron4j.Scheduler;
import it.sauronsoftware.cron4j.Task;
import it.sauronsoftware.cron4j.TaskExecutionContext;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class AbstractWechatAPI {

	@Getter
	public AccessToken accessToken;

	@Getter
	public JsapiTicket jsapiTicket;

	@Setter
	protected WechatEnv wechatEnv;

	// 是否内部刷新：默认为true，内部刷新无法用于集群环境
	@Setter
	private boolean innerRefresh;

	public AbstractWechatAPI(WechatEnv wechatEnv, boolean innerRefresh) {
		this.wechatEnv = wechatEnv;
		this.innerRefresh = innerRefresh;
		doTask();
		if (this.innerRefresh) {
			Scheduler scheduler = new Scheduler();
			// 用定时器定时刷新access_token和jsapi_ticket，每个整点刷新一次
			scheduler.schedule("0 * * * *", new Task() {
				@Override
				public void execute(TaskExecutionContext context) throws RuntimeException {
					doTask();
				}
			});
			scheduler.start();
		}
	}

	/**
	 * 执行一次刷新票据任务
	 */
	private void doTask() {
		refreshAccessToken();
		refreshJsapiTicket();
	}

	/**
	 * access_token是公众号的全局唯一票据，公众号调用各接口时都需使用access_token
	 */
	protected AccessToken gainAccessToken() {
		Map<String, String> params = Maps.newLinkedHashMap();
		params.put("appid", wechatEnv.getAppid());
		params.put("secret", wechatEnv.getAppsecret());
		AccessToken accessToken = HttpsUtil.get(ACCESS_TOKEN, params, AccessToken.class);
		// 计算截止时间（提前5s）
		Long deadlineTime = System.currentTimeMillis() + accessToken.getExpires_in() - 5000;
		accessToken.setDeadline(new Date(deadlineTime));
		return accessToken;
	}

	/**
	 * 刷新access_token
	 */
	public void refreshAccessToken() {
		accessToken = gainAccessToken();
		log.debug(System.currentTimeMillis() + "");
		log.debug("accessToken = " + accessToken);
	}

	/**
	 * 刷新jsapi_ticket
	 */
	private void refreshJsapiTicket() {
		jsapiTicket = gainJsapiTicket();
		log.debug(System.currentTimeMillis() + "");
		log.debug("jsapiTicket = " + jsapiTicket);
	}

	/**
	 * jsapi_ticket是公众号用于调用微信JS接口的临时票据
	 */
	private JsapiTicket gainJsapiTicket() {
		Map<String, String> params = Maps.newLinkedHashMap();
		String access_token = this.accessToken.getAccess_token();
		Assert.hasText(access_token);
		params.put("access_token", access_token);
		params.put("type", "jsapi");
		JsapiTicket jsapiTicket = HttpsUtil.get(JSAPI_TICKET, params, JsapiTicket.class);
		// 计算截止时间（提前5s）
		Long deadlineTime = System.currentTimeMillis() + jsapiTicket.getExpires_in() - 5000;
		jsapiTicket.setDeadline(new Date(deadlineTime));
		return jsapiTicket;
	}

}
